/**
 * @file       bsp_uart.cpp
 * @author     MatCoreShu (2874567545@qq.com)
 * @date       2025-05-21
 * @version    1.0
 * @copyright  Copyright (c) 2025 [ zhangshuoshi ]
 * @API说明     (API Documentation)
 * ==============================================
    void uart_show_data(Uart_t *ctx)
    Uart_t* Context_init_uart(const char *name, int baud_rate, int data_bits, int stop_bits, int parity) 
    void uart_deinit(Uart_t **ctx_ptr) 
    int uart_init(Uart_t *ctx, int _flags)
    ssize_t uart_to_send(int fd, const void *data, size_t length) 
    void uart_to_send_multidata(int fd, void *data, size_t data_size) 
    int uart_send_h265_frame(int fd, const void *data, size_t data_size) 
    void uart_to_send_multidata(int fd, void *data, size_t data_size) 
 * ==============================================
 */
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <stdlib.h>

#include "debug_log.h"
#include "bsp_uart.h"
#include "bsp_video.h"
#include "bsp_pthread.h"
#include "bsp_encoder.h"
#include "bsp_mjpeg.h"

//这部分或者修改成 Bsp_Global_fd 进行全局引用也可以
int *mcu_fd      = NULL;      
int *laser_fd    = NULL;
int *vis_fd      = NULL;    
int *icr_fd      = NULL;    //红外sub通信：管理上电相关指令
int *icrlens_fd  = NULL;    //红外镜头通信：管理尽头相关指令（聚焦、缩放）

volatile int thread1_should_exit  = 0;
volatile int thread1_write_data_to_uart  = 0; // 0 不写入 1 写入

volatile int thread2_should_exit = 0;
volatile int thread2_write_data_to_uart  = 0; // 0 不写入 1 写入
volatile int VIDEO_SELECT = -1; // 当前选中的视频设备

// 初始化串口上下文
Uart_t* uart_init_context(const char* name, int baudcfg, int datacfg, int stopcfg, int paritycfg) {
    Uart_t* ctx = (Uart_t*)malloc(sizeof(Uart_t));
    if (!ctx) {
        perror("内存分配失败");
        return NULL;
    }
    memset(ctx, 0, sizeof(Uart_t));
    
    ctx->name = strdup(name);
    if (!ctx->name) {
        free(ctx);
        perror("字符串复制失败");
        return NULL;
    }
    
    ctx->fd = -1;
    ctx->baud_rate = baudcfg;
    ctx->data_bits = datacfg;
    ctx->stop_bits = stopcfg;
    ctx->parity = paritycfg;  // 无校验
    
    // 初始化超时参数
    ctx->sec_ts = 0;
    ctx->chr = 0;
    
    return ctx;
}

// 释放串口上下文
void uart_free_context(Uart_t* ctx) {
    if (ctx) {
        if (ctx->fd >= 0) {
            close(ctx->fd);
            ctx->fd = -1;
        }
        if (ctx->name) {
            free(ctx->name);
            ctx->name = NULL;
        }
        free(ctx);
    }
}

// 显示串口配置信息
void uart_show_data(Uart_t *ctx)
{
    if (ctx == NULL)
    {
        perror("Uart_t context is NULL");
        return;
    }
    
    printf("\tUART_fd:[%d]\n", ctx->fd); 
    printf("\tUART_name:[%s]\n", ctx->name); 
    printf("\tUART_baudrate:[%d]\n", ctx->baud_rate);
    printf("\tUART_databits:[%d]\n", ctx->data_bits);
    printf("\tUART_stopbits:[%d]\n", ctx->stop_bits);
    printf("\tUART_parity:[%c]\n", ctx->parity);
}

void uart_deinit(Uart_t **ctx_ptr) 
{
    if (ctx_ptr && *ctx_ptr) {  // 检查二级指针非空且指向有效内存
        Uart_t *ctx = *ctx_ptr;
        
        if (ctx->fd > 0) {
            close(ctx->fd);
            ctx->fd = -1;
        }
        
        free(ctx->name);  // 释放动态分配的 name 指针
        free(ctx);        // 释放结构体本身
        *ctx_ptr = NULL;  // 关键：置空外部指针
    }
}
// 打开并配置串口
int open_and_configure_uart(Uart_t *ctx, int _flags)
{
    if (!ctx) {
        perror("Uart_t context is NULL");
        return -1;
    }
    
    // 关闭已打开的文件描述符
    if (ctx->fd >= 0) {
        close(ctx->fd);
        ctx->fd = -1;
    }
    
    // 打开串口设备
    ctx->fd = open(ctx->name, _flags);
    if (ctx->fd < 0) {
        printf("打开串口 %s 失败: %s\n", ctx->name, strerror(errno));
        return -1;
    }
    
    // 配置串口参数
    struct termios options;
    if (tcgetattr(ctx->fd, &options) != 0) {
        perror("获取串口属性失败");
        close(ctx->fd);
        ctx->fd = -1;
        return -1;
    }
    
    // 清除控制模式标志
    options.c_cflag &= ~CSIZE;
    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    options.c_oflag &= ~OPOST;
    options.c_iflag &= ~(IXON | IXOFF | IXANY);
    options.c_iflag &= ~(BRKINT | INPCK | ISTRIP | IXON);
    options.c_iflag &= ~ICRNL;

    // 设置超时参数
    if (ctx->sec_ts > 0 || ctx->chr > 0)
    {
        options.c_cc[VTIME] = ctx->sec_ts;
        options.c_cc[VMIN] = ctx->chr;
    }
    else {
        options.c_cc[VTIME] = 0;
        options.c_cc[VMIN] = 0;
    }

    // 设置波特率
    switch (ctx->baud_rate) 
    {
        case 9600:
            cfsetispeed(&options, B9600);
            cfsetospeed(&options, B9600);
            break;
        case 19200:
            cfsetispeed(&options, B19200);
            cfsetospeed(&options, B19200);
            break;
        case 38400:
            cfsetispeed(&options, B38400);
            cfsetospeed(&options, B38400);
            break;
        case 57600:
            cfsetispeed(&options, B57600);
            cfsetospeed(&options, B57600);
            break;
        case 115200:
            cfsetispeed(&options, B115200);
            cfsetospeed(&options, B115200);
            break;
        case 1152000:
            cfsetispeed(&options, B1152000);
            cfsetospeed(&options, B1152000);
            break;
        case 1500000:
            cfsetispeed(&options, B1500000);
            cfsetospeed(&options, B1500000);
            break;
        case 3000000:
            cfsetispeed(&options, B3000000);
            cfsetospeed(&options, B3000000);
            break;
        case 4000000:
            cfsetispeed(&options, B4000000);
            cfsetospeed(&options, B4000000);
            break;
        default:
            printf("警告: 不支持的波特率 %d，使用默认值 115200\n", ctx->baud_rate);
            cfsetispeed(&options, B115200);
            cfsetospeed(&options, B115200);
            break;
    }

    options.c_cflag |= CLOCAL | CREAD;
    
    // 设置校验位
    switch (ctx->parity) 
    {
        case 'O':
            options.c_cflag |= PARENB;
            options.c_cflag |= PARODD;
            options.c_iflag |= (INPCK | ISTRIP);
            break;
        case 'E':
            options.c_cflag |= PARENB;
            options.c_cflag &= ~PARODD;
            options.c_iflag |= (INPCK | ISTRIP);
            break;
        case 'N':
            options.c_cflag &= ~PARENB;
            break;
        default:
            printf("警告: 不支持的校验位 %c，使用默认值 无校验\n", ctx->parity);
            options.c_cflag &= ~PARENB;
            break;
    }
    
    // 设置数据位
    switch (ctx->data_bits) 
    {
        case 7:
            options.c_cflag &= ~CSIZE;
            options.c_cflag |= CS7;
            break;
        case 8:
            options.c_cflag &= ~CSIZE;
            options.c_cflag |= CS8;
            break;
        default:
            printf("警告: 不支持的数据位 %d，使用默认值 8\n", ctx->data_bits);
            options.c_cflag &= ~CSIZE;
            options.c_cflag |= CS8;
            break;
    }
    
    // 设置停止位
    switch (ctx->stop_bits) 
    {
        case 1:
            options.c_cflag &= ~CSTOPB;
            break;
        case 2:
            options.c_cflag |= CSTOPB;
            break;
        default:
            printf("警告: 不支持的停止位 %d，使用默认值 1\n", ctx->stop_bits);
            options.c_cflag &= ~CSTOPB;
            break;
    }
    
    // 应用配置
    if (tcsetattr(ctx->fd, TCSANOW, &options) < 0) {
        perror("设置串口属性失败");
        close(ctx->fd);
        ctx->fd = -1;
        return -1;
    }
    
    // 清空输入输出缓冲区
    tcflush(ctx->fd, TCIOFLUSH);
    
    return 0;
}
// 从串口接收数据
int receive_data(Uart_t* ctx, unsigned char* buf, int max_len, int timeout_ms) {
    if (!ctx || ctx->fd < 0 || !buf || max_len <= 0) {
        return -1;
    }
    
    fd_set readfds;
    struct timeval tv;
    
    FD_ZERO(&readfds);
    FD_SET(ctx->fd, &readfds);
    
    // 设置超时
    tv.tv_sec = timeout_ms / 1000;
    tv.tv_usec = (timeout_ms % 1000) * 1000;
    
    int activity = select(ctx->fd + 1, &readfds, NULL, NULL, &tv);
    if (activity < 0) {
        perror("select错误");
        return -1;
    } else if (activity == 0) {
        return 0; // 超时，无数据
    } else {
        int n = read(ctx->fd, buf, max_len);
        if (n > 0) {
            return n;
        } else if (n == 0) {
            return 0; // 无数据
        } else {
            perror("读取数据失败");
            return -1;
        }
    }
}

// 向串口发送数据
int send_data(Uart_t* ctx, unsigned char* data, int len) {
    if (!ctx || ctx->fd < 0 || !data || len <= 0) {
        return -1;
    }
    
    int ret = write(ctx->fd, data, len);
    if (ret != len) {
        printf("发送失败，预期发送 %d 字节，实际发送 %d 字节\n", len, ret);
        return -1;
    }
    return 0;
}

void uart_to_send_multidata(int fd, void *data, size_t data_size) 
{
    if (fd < 0 || data == NULL || data_size == 0) {
        fprintf(stderr, "Invalid arguments: fd = %d, data_size = %zu\n", fd, data_size);
        return;
    }

    size_t remaining = data_size;
    char *current = (char *)data;

    while (remaining > 0) {
        // 计算当前块大小：每次发送 BUFFER_SIZE 字节，最后一块可能更小
        size_t bytes_to_send = (remaining > BUFFER_SIZE) ? BUFFER_SIZE : remaining;

        // 发送数据块
        ssize_t bytes_sent = write(fd, current, bytes_to_send);

        if (bytes_sent == -1) {
            perror("Error writing to serial device");
            break; // 发生错误，终止发送
        }

        // 更新剩余数据和指针
        remaining -= bytes_sent;
        current += bytes_sent;

        // 处理部分发送（仅当非阻塞模式或设备限制时可能发生）
        if ((size_t)bytes_sent < bytes_to_send) {
            fprintf(stderr, "Partial send: Sent %zd/%zu bytes. Remaining: %zu\n", 
                    bytes_sent, bytes_to_send, remaining);
            
            // 非阻塞模式下可选择重试，阻塞模式下通常不会出现此情况
            if (errno == EAGAIN || errno == EWOULDBLOCK) {
                continue; // 重试当前块
            } else {
                break; // 其他错误，终止发送
            }
        }
    }

    // 发送完成提示（可选）
    if (remaining == 0) {
        fprintf(stdout, "Successfully sent %zu bytes in %zu chunks.\n", 
                data_size, (data_size + BUFFER_SIZE - 1) / BUFFER_SIZE);
    }
}
/******************************************** 
********************************************* 
*   发送H.265帧到串口
*/
// 定义帧头和帧尾常量
#define FRAME_HEADER_1 0xEB
#define FRAME_HEADER_2 0x90
#define FRAME_TAIL_1   0xAA
#define FRAME_TAIL_2   0x55
#define BLOCK_SIZE     1024
// #define MAX_RETRIES    5
// #define BASE_DELAY_USEC 10000
#define OUTPUT_FILE    "h265_frames.h265"  // 输出文件名

int uart_send_h265_frame(int fd, const void *data, size_t data_size) 
{
    /* 声明文件指针 */
    FILE *fp = NULL;
    
    if (fd < 0 || data == NULL || data_size == 0) {
        errno = EINVAL;
        return -1;
    }

    size_t remaining = data_size;
    const uint8_t *current = (const uint8_t *)data;
    
    // 打开文件用于二进制写入（追加模式）
    fp = fopen(OUTPUT_FILE, "ab");
    if (fp == NULL) {
        perror("Failed to open output file");
        return -1;
    }

#if 1  // 原始数据分块发送模式
    while (remaining > 0) {
        // 固定块大小为1024字节，不足则发送剩余字节
        size_t chunk_size = (remaining >= BLOCK_SIZE) ? BLOCK_SIZE : remaining;
        
        // 发送数据块
        ssize_t bytes_written = write(fd, current, chunk_size);
        if (bytes_written == -1) {
            perror("Write error");
            fclose(fp);
            return -1;
        }

        /* 保存原始数据到文件 */
        // fwrite(current, 1, chunk_size, fp);

        /* 固定延时 */
        usleep(BASE_DELAY_USEC);

        // 更新状态
        remaining -= bytes_written;
        current += bytes_written;
    }

#else  // 带帧头帧尾的分块发送模式
    int retries = 0;
    uint8_t block_seq = 0;  // 块序列号（0-255循环）
    
    // 帧结构：[EB 90] [块序列号] [数据长度高字节] [数据长度低字节] [数据块] [AA 55]
    uint8_t frame_header[5];  // 帧头总长度5字节
    frame_header[0] = 0xEB;   // FRAME_HEADER_1
    frame_header[1] = 0x90;   // FRAME_HEADER_2
    
    uint8_t frame_tail[2] = {0xAA, 0x55};  // FRAME_TAIL_1, FRAME_TAIL_2

    while (remaining > 0) {
        // 固定块大小为1024字节，不足则发送剩余字节
        size_t chunk_size = (remaining >= BLOCK_SIZE) ? BLOCK_SIZE : remaining;
        
        // 填充帧头：块序列号 + 数据长度（2字节，大端序）
        frame_header[2] = block_seq;        // 第3个字段：块序列号
        frame_header[3] = (chunk_size >> 8) & 0xFF;  // 数据长度高字节
        frame_header[4] = chunk_size & 0xFF;         // 数据长度低字节
        
        // 发送帧头（共5字节：EB 90 + 序列号 + 长度高 + 长度低）
        ssize_t header_written = write(fd, frame_header, 5);
        if (header_written != 5) {
            perror("Failed to write frame header");
            fclose(fp);
            return -1;
        }
        
        // 发送数据块
        ssize_t bytes_written = write(fd, current, chunk_size);
        if (bytes_written == -1) {
            if (errno == EAGAIN || errno == EWOULDBLOCK) {
                perror("Serial buffer full, retry");
                if (retries++ >= MAX_RETRIES) {
                    fclose(fp);
                    return -1;
                }
                continue;  // 重试发送当前块（序列号不变）
            } else {
                perror("Write error");
                fclose(fp);
                return -1;
            }
        }
        
        // 发送帧尾（2字节：AA 55）
        ssize_t tail_written = write(fd, frame_tail, sizeof(frame_tail));
        if (tail_written != sizeof(frame_tail)) {
            perror("Failed to write frame tail");
            fclose(fp);
            return -1;
        }

        /* 保存到文件：帧头 + 数据 + 帧尾 */
        fwrite(frame_header, 1, 5, fp);
        fwrite(current, 1, chunk_size, fp);
        fwrite(frame_tail, 1, 2, fp);

        /* 固定延时：按1024字节的理论耗时计算 */
        usleep(BASE_DELAY_USEC);

        // 更新状态：剩余数据、指针、序列号（0-255循环）
        remaining -= bytes_written;
        current += bytes_written;
        block_seq = (block_seq + 1) % 256;  // 序列号递增，溢出后从0开始
        retries = 0;  // 重置重试计数
    }
#endif

    // 等待所有数据发送完成（确保硬件缓冲区清空）
    if (tcdrain(fd) < 0) {
        perror("tcdrain failed");
        fclose(fp);
        return -1;
    }

    /* 关闭文件 */
    fclose(fp);

    return 0;
}
//方案二，流水号 + 确认帧机制，成功返回0，失败返回-1
int uart_send_video_frame(int fd, const void *frame_data, size_t data_length, uint16_t frame_id) 
{
    if (fd < 0 || frame_data == NULL || data_length == 0) {
        fprintf(stderr, "无效参数\n");
        return -1;
    }
    
    const uint8_t *newframe = (const uint8_t *)frame_data;
    // 计算需要发送的块数
    size_t total_blocks = (data_length + FRAME_DATA_SIZE - 1) / FRAME_DATA_SIZE;
    for (size_t block_idx = 0; block_idx < total_blocks; block_idx++) 
    {
        // 重新分配帧结构 EB 90 帧号 帧数据 AA 55
        SendFrame frame;
        
        // 设置帧头
        frame.header[0] = 0xEB;
        frame.header[1] = 0x90;
        
        // 设置帧号(小端格式)
        frame.frame_id = block_idx;  // 小端系统直接使用主机字节序
        
        // 计算当前块的数据
        size_t start_idx = block_idx * FRAME_DATA_SIZE;
        size_t copy_length = (start_idx + FRAME_DATA_SIZE > data_length) ? 
                             data_length - start_idx : FRAME_DATA_SIZE;
        
        // 复制数据到帧
        memcpy(frame.data, newframe + start_idx, copy_length);
        
        // 设置帧长(小端格式)
        // 帧长 = 帧号(2) + 帧长字段(2) + 数据区大小

        frame.frame_length = HEADER_SIZE + FRAME_ID_SIZE + FOOTER_SIZE + copy_length;;
        
        // 设置帧尾
        frame.footer[0] = 0xAA;
        frame.footer[1] = 0x55;
        
        // 循环写入，确保所有数据发送完成
        size_t bytes_sent = 0;
        const uint8_t* send_ptr = (const uint8_t*)&frame;
        
        while (bytes_sent < frame.frame_length) {
            ssize_t result = write(fd, (const uint8_t*)&frame + bytes_sent, frame.frame_length - bytes_sent);
            
            if (result < 0) {
                perror("发送失败，write返回错误");
                return -1;
            }
            printf("当前数据写入缓冲区：%ld\n",result);
            bytes_sent += result;
        }
        // 简单流控
        usleep(5000); // 5毫秒
        // 等待所有数据发送完成
        if (tcdrain(fd) < 0) {
            perror("tcdrain failed");
            return -1;
        }
    }



    return 0;
}

// 接收确认帧 失败返回 -1，成功返回 0
int uart_recv_ack_frame(int fd, uint16_t *frame_id) 
{
    if (fd < 0 || frame_id == NULL) {
        fprintf(stderr, "无效参数\n");
        return -1;
    }

    uint8_t buffer[HEADER_SIZE + FRAME_ID_SIZE + FOOTER_SIZE];
    size_t bytes_received = 0;
    int state = 0; // 0: 寻找帧头, 1: 读取帧号, 2: 读取帧尾

    // 设置超时时间（1秒）
    struct timeval timeout;
    timeout.tv_sec = 0;
    timeout.tv_usec = 33000;

    while (1)
    {
        fd_set readfs;
        FD_ZERO(&readfs);
        FD_SET(fd, &readfs);
        
        // 使用select()实现超时读取
        int result = select(fd + 1, &readfs, NULL, NULL, &timeout);
        if (result < 0) {
            perror("select() 错误");
            return -1;
        } else if (result == 0) {
            // 超时
            fprintf(stderr, "接收ACK超时\n");
            return -1;
        }

        //单字节顺序读取，避免粘包，半包数据问题
        uint8_t byte;
        if (read(fd, &byte, 1) != 1) {
            continue; // 读取失败，继续尝试
        }
        //状态机解析帧
        switch (state)
        {
            case 0:{ //查找帧头
            if (bytes_received == 0 && byte == 0xEB)
            {
                buffer[bytes_received++] = byte;
            } else if (bytes_received == 1 && bytes_received == 0x90)
            {
                buffer[bytes_received++] = byte;
                // 帧头接收完成，开始接收帧号
                state = 1;
            } else {
                //滑动窗口机制:即使保留当前字节，查找下一个合适的
                if (byte == 0xEB)
                {
                    buffer[0] = byte;
                    bytes_received = 1;
                } else {
                    bytes_received = 0; //重置，未找到帧头     
                }
            }
            
            } break;
            case 1:{ //查找帧号
            buffer[bytes_received++] = byte;

            if (bytes_received == HEADER_SIZE + FRAME_ID_SIZE)
            {
                state = 2;
            } 
            } break;
            case 3:{ //查找帧尾
            buffer[bytes_received++] = byte;
            if (bytes_received == sizeof(buffer)) {
                // 验证帧尾
                if (buffer[4] == 0xAA && buffer[5] == 0x55) {
                    // 提取帧号（小端格式）
                    *frame_id = (buffer[3] << 8) | buffer[2];
                    return 0; // 成功接收ACK
                } else {
                    fprintf(stderr, "帧尾验证失败: 0x%02X 0x%02X\n", buffer[4], buffer[5]);
                }
                
                // 重置状态机，继续寻找下一帧
                bytes_received = 0;
                state = 0;
            }
            } break;    
            default:{
            bytes_received = 0;
            state = 0;            
            }break;
        }
    }
    
    return -1;
}
/*
 * @Section: Data Update and Device Control
 * @Description: This section implements device command sending, response parsing, and device management.
 *               It uses a handler table to map device names to parsing functions, and provides a unified interface
 *               to send commands to different sub-devices (e.g., laser, visible light, infrared).
 * @Components:
 *   - DeviceHandler: Struct array mapping device names to response parsers.
 *   - find_device_handler: Locate device handler by name.
 *   - send_and_wait: Common logic for sending commands and waiting for responses.
 *   - parse_*_response: Device-specific response parsing functions.
 *   - SendCmdToSubdev: Main interface to send commands to sub-devices and trigger parsing.
 * 
 */
/* ------------Sub dev parse response--------------*/
void parse_laser_response(const unsigned char* response, int bytes_read) 
{
    //recv hex data
    printf("Laser Response (%d bytes): [", bytes_read);
    for (int i = 0; i < bytes_read; i++) {
        printf("%02X ", response[i]);
    }
    printf("]\n");
    
    /* Sub device parsing and analysis section */
    if (bytes_read < 15) {
        printf("Invalid laser response length\n");
        return;
    }
    /* Analyze self-test command response */ 
    if (response[0] == 0xCC && response[14] == 0x55) {
        int8_t env_temp         = response[2];  //环境温度
        uint8_t self_check_info = response[3];  //自检信息     03:正常出光     FF：不出光
        uint8_t work_mode       = response[4];        //工作模式     01：高强度工作  00：正常
        uint8_t checksum        = response[13];        //校验字       

        printf("环境温度: %d °C\n", env_temp);  // 输出解析结果
        if (self_check_info == 0x03){//自检信息
            printf("自检信息: 正常出光\n");
        } 
        else if (self_check_info == 0xFF){
            printf("自检信息: 不出光\n");
        }else {
            printf("自检信息: 未知状态\n");
        }
        
        if (work_mode == 0x01){//工作模式
            printf("工作模式: 高强度工作\n");
        } else if (work_mode == 0x00){
            printf("工作模式: 正常工作\n");
        } else {
            printf("工作模式: 未知模式\n");
        }
        printf("校验字: 0x%02X\n", checksum);
    }
    /* Analyze regular data response data and update it to the global variable structure */ 
    if (response[0] == 0xAA && response[14] == 0x55) {
        uint8_t target_count = response[1];     // *解析目标个数
        uint32_t laser_first_distance   = (response[2] << 16) | (response[3] << 8) | response[4];
        uint32_t   laser_end_distance   = (response[5] << 16) | (response[6] << 8) | response[7];
        uint8_t        measure_status   = (response[8]);        // *判断常规状态指令
        uint32_t light_emission_count   = (response[9] << 24) | (response[10] << 16) | (response[11] << 8) | response[12];  // *解析出光次数

        /* debug: 在解析回调函数中尽可能地使用静态缓冲区 */
        static laser_data_t debug;
        memset(&debug, 0, sizeof(laser_data_t));
        debug.first_distance = laser_first_distance;
        debug.end_distance   = laser_end_distance;
        debug.light_emission_count = light_emission_count;
        debug.target_count   = target_count;
        Laser_show(&debug);

        /* Global variable data update */

    }
 
}
static void parse_vis_response(const unsigned char* response, int bytes_read) 
{
    //recv hex data
    printf("Vis Response (%d bytes): [", bytes_read);
    for (int i = 0; i < bytes_read; i++) {
        printf("%02X ", response[i]);
    }
    printf("]\n");
    
    /* Sub device parsing and analysis section */

}
static void parse_icr_response(const unsigned char* response, int bytes_read) 
{
    //recv hex data
    printf("ICR Response (%d bytes): [", bytes_read);
    for (int i = 0; i < bytes_read; i++) {
        printf("%02X ", response[i]);
    }
    printf("]\n");
    
    /* Sub device parsing and analysis section */

}
// dev handle list
static const DeviceHandler device_handlers[] = {
    {"laser",   parse_laser_response},
    {"vis",     parse_vis_response},
    {"icr",     parse_icr_response},
    // 可扩展新设备
};
// find dev list 
static const DeviceHandler* find_device_handler(const char* name) 
{
    for (size_t i = 0; i < sizeof(device_handlers) / sizeof(device_handlers[0]); i++) 
    {
        if (strcmp(name, device_handlers[i].name) == 0) 
        {
            return &device_handlers[i];
        }
    }
    return NULL;
}
// 只发送命令（公共逻辑）
// send_and_wait(fd, CMD,sizeof(CMD),buf,sizeof(CMD))
static int OnlysendSubDev(int fd, const unsigned char* cmd, int len) 
{
    // 发送命令
    return write(fd, cmd, len);
}
// 发送命令并等待响应（公共逻辑）
// send_and_wait(fd, CMD,sizeof(CMD),buf,sizeof(CMD))
static int send_and_wait(int fd, const unsigned char* cmd, int len, int timeout, unsigned char* buf, int buf_size) 
{
    // 发送命令
    int bytes_written = write(fd, cmd, len);
    if (bytes_written != len) {
        printf("%d\n",bytes_written);
        perror("Write failed");
        return -1;
    }
    
    // 等待响应
    struct timeval tv = { timeout / 1000, (timeout % 1000) * 1000 };
    fd_set readfds;
    FD_ZERO(&readfds);
    FD_SET(fd, &readfds);
    
    int active = select(fd + 1, &readfds, NULL, NULL, &tv);
    if (active <= 0) {
        perror("Select timeout");
        return -2;
    }
    
    // 读取响应
    return read(fd, buf, buf_size);
}



// 主函数
int SendCmdToSubdev(const char* name, int fd, unsigned char* cmd, int len, int timeout) 
{
    /* 1 Matching sub equipment */
    const DeviceHandler* handler = find_device_handler(name);
    if (!handler) {
        fprintf(stderr, "Unknown device: %s\n", name);
        return -1;
    }
    //Way1: send subcmd and wait for response,发一次读一次（针对单次的）
    /* 2 Define a buffer to receive response data only one */
    unsigned char response_buf[256];
    int bytes_read = send_and_wait(fd, cmd, len, timeout, response_buf, sizeof(response_buf));
    /* 3 Analyze sub device data */
    if (bytes_read > 0) {
        handler->parser(response_buf, bytes_read);
    }

    /* only send subcmd */
    // int bytes_read = OnlysendSubDev(fd, cmd, len);
    // if (bytes_read < 0) {
    //     fprintf(stderr, "Failed to send command to %s: %s\n", name, strerror(errno));
    //     return -1;
    // }
    return bytes_read;
}

/**
 * @brief 解析并执行MCU通过UART发送的指令
 *
 * @param fd         设备文件描述符集合指针
 * @param buf        接收数据缓冲区
 * @param len        接收数据长度
 */
void UartGetMcuData(int fd, uint8_t *buf, int len) 
{
    printf("UartGetMcuData: Processing %d bytes\n", len);
    int8_t LOG_OK = 1;
    int ret = -1;
    // 1. 基础校验
    if (len < 12) {
        printf("Error: Invalid command length. Expected at least 12 bytes, received %d\n", len);
        return;
    }

    // 2. 日志输出优化
    printf("\n=== UART Received Data ===\n");
    printf("Total bytes: %d\n", len);
    printf("Binary data: [");
    for (int i = 0; i < len; i++) {
        printf("%02X ", buf[i]);
    }
    printf("\b]\n");

    // 3. 同步码校验
    const uint8_t SYNC_CODE_H = 0xEB;
    const uint8_t SYNC_CODE_L = 0x90;
    if (buf[0] != SYNC_CODE_H || buf[1] != SYNC_CODE_L) {
        printf("Error: Sync code mismatch (expected 0xEB90)\n");
        return;
    }

    // 4. 校验和计算优化
    uint8_t calculatedChecksum = 0;
    for (int i = 0; i < 11; i++) {
        calculatedChecksum += buf[i];
    }
    if (buf[11] != calculatedChecksum) {
        printf("Error: Checksum verification failed (calculated=0x%02X, received=0x%02X)\n", 
               calculatedChecksum, buf[11]);
        return;
    }

    // 5. 数据解析结构化
    // 6. 控制码处理逻辑优化,包含解析主设备协议以及发送子设备的分发协议
    printf("Processing command: 0x%02X\n", buf[2]);
    /*cmd init: laser*/
    //单次测距 多次测距 停止测距 自检
    unsigned char SLP_LASER_CMD_SINGLE[6]  = {0x55 ,0xF2 ,0x00 ,0x00 ,0xF2 ,0xAA};
    unsigned char SLP_LASER_CMD_1Hz[6]     = {0x55 ,0xF3 ,0x01 ,0x00 ,0xF2 ,0xAA};
    unsigned char SLP_LASER_CMD_5Hz[6]     = {0x55 ,0xF3 ,0x02 ,0x00 ,0xF1 ,0xAA};
    unsigned char SLP_LASER_CMD_STOP[6]    = {0x55 ,0xF3 ,0x02 ,0x00 ,0xF3 ,0xAA};
    unsigned char SLP_LASER_CMD_CHECK[6]   = {0x55 ,0xF0 ,0x00 ,0x00 ,0xF0 ,0xAA};
    /*cmd init: vis */
    //打开J30串口进行直通通信
    unsigned char SLP_VIS_CMD_UART_J30_OPEN[9] = {0x81 ,0x0A ,0x02 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0xFF};  
    //数字变焦开
    unsigned char SLP_VIS_CMD_DZOOM_ON[6]     = {0x81 ,0x01 ,0x04 ,0x06 ,0x02, 0xFF};  
    //数字变焦关
    unsigned char SLP_VIS_CMD_DZOOM_OFF[6]     = {0x81 ,0x01 ,0x04 ,0x06 ,0x03, 0xFF};  
    // 打开可见 关闭可见 
    // unsigned char FLP_VIS_CMD_SUBDEV_POWERON[12]   = {0xEB, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x7C}; // 打开可见光
    // unsigned char FLP_VIS_CMD_SUBDEV_POWEROFF[12]  = {0xEB, 0x90, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x7D}; // 关闭可见光

    //unsigned char FLP_VIS_CMD_SUBDEV_CTLMODE[12]  = {0xEB, 0x90, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x7D}; // 可见光模式选择
    //unsigned char FLP_ICR_CMD_SUBDEV_CTLMODE[12]  = {0xEB, 0x90, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x7D}; // 可见光模式选择

    unsigned char SLP_VIS_CMD_MANNUAL_MODE[6]     = {0x81 ,0x01 ,0x04 ,0x39 ,0x03 ,0xFF};  //手动模式
    unsigned char SLP_VIS_CMD_AUTO_MODE[6]        = {0x81 ,0x01 ,0x04 ,0x39 ,0x00 ,0xFF};  //自动模式

    unsigned char SLP_VIS_CMD_DIGITALZOOM_ON[6] = {0x81, 0x01, 0x04 ,0x06 ,0x02 ,0xFF};  //可见光数字变倍开
    unsigned char SLP_VIS_CMD_DIGITALZOOM_OFF[6] = {0x81, 0x01, 0x04 ,0x06 ,0x03 ,0xFF};  //可见光数字变倍关


    unsigned char SLP_VIS_CMD_DIGITAL_ZOOM_COMBINED[6] = {0x81, 0x01, 0x04 ,0x36 ,0x00 ,0xFF};  //可见光数字变倍开（该模式是光学和数字结合模式）
    unsigned char SLP_VIS_CMD_DIGITAL_ZOOM_SEPARATE[6] = {0x81, 0x01, 0x04 ,0x36 ,0x01 ,0xFF};  //可见光数字变倍开（该模式是光学和数字分离模式）


    //以下命令必须再手动模式下才可以使用
    unsigned char SLP_VIS_CMD_FIXED_GAIN[9]          = {0x81 ,0x01 ,0x04 ,0x4D ,0x00 ,0x00 ,0x00 ,0x00 ,0xFF};  //固定增益(00 - 0F)

    //光学缩放
    unsigned char SLP_VIS_CMD_CONTINUOUS_ZOOM_UP[7]  = {0x81, 0x01, 0x04, 0x07, 0x02,0xFF}; //可见光持续放大+
    unsigned char SLP_VIS_CMD_CONTINUOUS_ZOOM_DOWN[7]= {0x81, 0x01, 0x04, 0x07, 0x03,0xFF}; //可见光持续缩小-
    unsigned char SLP_VIS_CMD_CONTINUOUS_ZOOM_STOP[7]= {0x81, 0x01, 0x04, 0x07, 0x00,0xFF}; //可见光    停止
    //数字缩放

    unsigned char SLP_VIS_CMD_CONTINUOUS_FOCUS_UP[7]  = {0x81, 0x01, 0x04, 0x08, 0x02,0xFF}; //可见光持续聚焦+
    unsigned char SLP_VIS_CMD_CONTINUOUS_FOCUS_DOWN[7]= {0x81, 0x01, 0x04, 0x08, 0x03,0xFF}; //可见光持续聚焦-
    unsigned char SLP_VIS_CMD_CONTINUOUS_FOCUS_STOP[7]= {0x81, 0x01, 0x04, 0x08, 0x00,0xFF}; //可见光持续聚焦 停止

    /*cmd init: ir  */
    // 打开红外 关闭红外 红外参数配置 探测器上电 视频处理电路上电 开始摄像
    // unsigned char FLP_ICR_CMD_SUBDEV_POWERON[12]     = {0xEB, 0x90, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x7E}; // 打开红外
    // unsigned char FLP_ICR_CMD_SUBDEV_POWEROFF[12]    = {0xEB, 0x90, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x7F}; // 关闭红外
    /* Subdev contract */
    unsigned char SLP_ICR_CMD_SET_OPTION[18] = {0x55, 0xAA, 0x73, 0x95, 0x00, 0xA0, 
                                            0x10, 0x00, 0x30, 0x0D, 0x17, 0x00, 
                                            0x00, 0x00, 0x00, 0x05, 0x50, 0x61};

    unsigned char SLP_ICR_CMD_DETECTOR_POWERON[6]   = {0x55, 0xAA, 0x73, 0xB1, 0xB1,0xD5};
    unsigned char SLP_ICR_CMD_VPROCRCUT_POWERON[6]  = {0x55, 0xAA, 0x73, 0xB3, 0xB3,0xD9};
    unsigned char SLP_ICR_CMD_VIDEO_START[6]        = {0x55, 0xAA, 0x73, 0xB5, 0xB5,0xDD};
    //停止摄像 视频处理电路下电  探测器下电

    /* Subdev contract */
    unsigned char SLP_ICR_CMD_DETECTOR_POWEROFF[6]  = {0x55, 0xAA, 0x73, 0xB2, 0xB2,0xD7};
    unsigned char SLP_ICR_CMD_VPROCRCUT_POWEROFF[6] = {0x55, 0xAA, 0x73, 0xB4, 0xB4,0xDB};
    unsigned char SLP_ICR_CMD_VIDEO_STOP[6]         = {0x55, 0xAA, 0x73, 0xB6, 0xB6,0xDF};

   
 

   
    unsigned char SLP_ICR_CMD_SINGLESTEP_ZOOM_UP[7]         = {0xFF, 0x01, 0x00, 0x07, 0x00,0x56, 0x5E}; //红外单步变倍+
    unsigned char SLP_ICR_CMD_SINGLESTEP_ZOOM_DOWN[7]       = {0xFF, 0x01, 0x00, 0x07, 0x00,0x55, 0x5D}; //红外单步变倍-
    unsigned char SLP_ICR_CMD_SINGLESTEP_FOCUS_UP[7]        = {0xFF, 0x01, 0x00, 0x07, 0x00,0x58, 0x60}; //红外单步聚焦变倍+
    unsigned char SLP_ICR_CMD_SINGLESTEP_FOCUS_DOWN[7]      = {0xFF, 0x01, 0x00, 0x07, 0x00,0x57, 0x5F}; //红外单步聚焦变倍-
   




    /* ctl cmd */
    unsigned char FLP_ICR_CMD_CONTINUOUS_ZOOM_UP[12]    = {0xEB, 0x90, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xD0}; //红外持续变倍+
    unsigned char FLP_ICR_CMD_CONTINUOUS_ZOOM_DOWN[12]  = {0xEB, 0x90, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0xD1}; //红外持续变倍-
    unsigned char FLP_ICR_CMD_CONTINUOUS_FOCUS_UP[12]    = {0xEB, 0x90, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0xD2}; //红外持续聚焦变倍+
    unsigned char FLP_ICR_CMD_CONTINUOUS_FOCUS_DOWN[12]  = {0xEB, 0x90, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0xD3}; //红外持续聚焦变倍-
    
    unsigned char FLP_ICR_CMD_SINGLESTEP_ZOOM_UP[12]    = {0xEB, 0x90, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0xD4}; //红外单步变倍+
    unsigned char FLP_ICR_CMD_SINGLESTEP_ZOOM_DOWN[12]  = {0xEB, 0x90, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0xD5}; //红外单步变倍-
    unsigned char FLP_ICR_CMD_SINGLESTEP_FOCUS_UP[12]    = {0xEB, 0x90, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0xD6}; //红外单步聚焦变倍+
    unsigned char FLP_ICR_CMD_SINGLESTEP_FOCUS_DOWN[12]  = {0xEB, 0x90, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0xD7}; //红外单步聚焦变倍-
    unsigned char FLP_ICR_CMD_STOP_ZF[12]  = {0xEB, 0x90, 0x60, 0x00, 0x00, 0x00, 0x00, 0x02, 0xFF, 0x00, 0x00, 0xDC}; //红外单步聚焦变倍-
   

    pthread_t vis_thd_id, icr_thd_id;


    switch (buf[2]) {
        /* 激光模块命令范围（0xC0 ~ 0xC4）*/
        case 0xC0: { // 单次测距
            ret = send_data(g_uart_laser,SLP_LASER_CMD_SINGLE,sizeof(SLP_LASER_CMD_SINGLE));
            break;
        }
        case 0xC1: { // 1Hz多次测距
            ret = send_data(g_uart_laser,SLP_LASER_CMD_1Hz,sizeof(SLP_LASER_CMD_1Hz));
            break;
        }
        case 0xC2: { // 5Hz多次测距
            ret = send_data(g_uart_laser,SLP_LASER_CMD_5Hz,sizeof(SLP_LASER_CMD_5Hz));
            break;
        }
        case 0xC3: { // 停止测距
            ret =  send_data(g_uart_laser,SLP_LASER_CMD_STOP,sizeof(SLP_LASER_CMD_STOP));
            break;
        }
        case 0xC4: { // 自检
            ret =  send_data(g_uart_laser,SLP_LASER_CMD_CHECK,sizeof(SLP_LASER_CMD_CHECK));
            break;
        }
        case 0xC5: { // 打开激光使能
            const char* openCmd = "sudo /home/remote/project/build/test_enblelasergpio_demo";
            printf("执行打开激光使能命令: %s\n", openCmd);
            
            int status = system(openCmd);
            if (status == -1) {
                perror("打开激光使能命令执行失败");
            } else if (WIFEXITED(status)) {
                printf("打开命令执行完毕，退出状态: %d\n", WEXITSTATUS(status));
            } else if (WIFSIGNALED(status)) {
                printf("打开命令被信号终止: %d\n", WTERMSIG(status));
            }
            break;
        }
        case 0xC6: { // 关闭激光使能
            const char* closeCmd = "sudo /home/remote/project/build/test_unablelasergpio_demo";
            printf("执行打开激光使能命令: %s\n", closeCmd);
            
            int status = system(closeCmd);
            if (status == -1) {
                perror("打开激光使能命令执行失败");
            } else if (WIFEXITED(status)) {
                printf("打开命令执行完毕，退出状态: %d\n", WEXITSTATUS(status));
            } else if (WIFSIGNALED(status)) {
                printf("打开命令被信号终止: %d\n", WTERMSIG(status));
            }
            break;
        }
        /* vis module */
        case 0x01: {// 打开可见光 1080p
#if 1
            pthread_mutex_lock(&select_video_lock);         
            thread1_write_data_to_uart = 1;
            
                // 检查线程是否已经在运行
                if (VIDEO_SELECT == VIDEO_DEV_VISIBLE) {
                    // 检查线程是否存在并且未请求退出
                    if (vis_thd_id != 0 && !thread1_should_exit) {
                        thread1_write_data_to_uart = 1;
                        printf("警告：可见光线程已在运行，无需重复启动\n");
                        pthread_mutex_unlock(&select_video_lock);
                        break;
                    }
                    
                    // 线程存在但请求退出，等待其结束
                    if (vis_thd_id != 0) {
                        thread1_should_exit = 1;
                        pthread_mutex_unlock(&select_video_lock);
                        
                        // 等待线程退出
                        signal_thread_to_exit(&vis_thd_id, &thread1_should_exit);
                        
                        pthread_mutex_lock(&select_video_lock);
                    }
                }
                
                // 设置当前视频设备为可见光
                VIDEO_SELECT = VIDEO_DEV_VISIBLE;
                thread1_should_exit = 0; // 重置退出标志
                
                pthread_mutex_unlock(&select_video_lock);
                
                // 全局变量声明（确保mjpeg_encoder为全局变量）
                static VideoEncoderContext *mjpeg_encoder = NULL;
                
                // 若编码器已存在但未运行，重新初始化
                if (mjpeg_encoder != NULL && !mjpeg_encoder->is_running) {
                    printf("##[DEBUG] 编码器已存在但未运行，重新初始化\n");
                    int ret = video_encoder_init(mjpeg_encoder);
                    if (ret != 0) {
                        fprintf(stderr, "编码器重新初始化失败，错误码: %d\n", ret);
                        break;
                    }
                }
                
                // 首次创建编码器
                if (mjpeg_encoder == NULL) {
                    const EncoderParams params = {"/dev/video20", "output_h265.h265", 1920, 1080, 30, 0, ENCODING_FORMAT_H265, 1};
                    // 创建编码器
                    mjpeg_encoder = video_encoder_create(&params);
                    if (!mjpeg_encoder) {
                        fprintf(stderr, "创建编码器失败\n");
                        VIDEO_SELECT = -1;
                        break;
                    }
                    
                    // 初始化编码器
                    int ret = video_encoder_init(mjpeg_encoder);
                    if (ret != 0) {
                        fprintf(stderr, "编码器初始化失败，错误码: %d\n", ret);
                        video_encoder_destroy(mjpeg_encoder);
                        mjpeg_encoder = NULL;
                        VIDEO_SELECT = -1;
                        break;
                    }
                }
                
                // 创建新的编码线程（仅当线程未启动时）
                if (vis_thd_id == 0 || !mjpeg_encoder->is_running) {
                    if (pthread_create(&vis_thd_id, NULL, encode_thread_mjpeg, mjpeg_encoder) != 0) {
                        printf("创建可见光线程失败\n");
                        VIDEO_SELECT = -1;
                    } else {
                        printf("可见光线程已启动，ID=%lu\n", (unsigned long)vis_thd_id);
                    }
                }
                
                thread1_write_data_to_uart = 1;
                break;
#else
            pthread_mutex_lock(&select_video_lock);
                // 如果编码器已创建但暂停，直接恢复
            if (mjpeg_encoder != NULL && !mjpeg_encoder->is_running) {
                printf("##[DEBUG] 编码器已存在但未运行，重新初始化\n");
                int ret = video_encoder_init(mjpeg_encoder);
                if (ret != 0) {
                    fprintf(stderr, "编码器重新初始化失败，错误码: %d\n", ret);
                    pthread_mutex_unlock(&select_video_lock);
                    break;
                }
            }
            if (mjpeg_encoder != NULL && mjpeg_encoder->is_running && mjpeg_encoder->paused) {
                // 恢复已暂停的编码器
                video_encoder_resume(mjpeg_encoder);
                printf("可见光线程: 已恢复编码\n");
                pthread_mutex_unlock(&select_video_lock);
                break;
            }
               // 首次创建或完全停止后的重新创建
            const EncoderParams params = {
                "/dev/video20", "output_h265.h265", 1920, 1080, 30, 0, ENCODING_FORMAT_H265, 1
            };
            
            // 创建新编码器
            if (mjpeg_encoder == NULL) {
                mjpeg_encoder = video_encoder_create(&params);
                if (!mjpeg_encoder) {
                    fprintf(stderr, "创建编码器失败\n");
                    pthread_mutex_unlock(&select_video_lock);
                    break;
                }
                
                int ret = video_encoder_init(mjpeg_encoder);
                if (ret != 0) {
                    fprintf(stderr, "编码器初始化失败，错误码: %d\n", ret);
                    video_encoder_destroy(mjpeg_encoder);
                    mjpeg_encoder = NULL;
                    pthread_mutex_unlock(&select_video_lock);
                    break;
                }
            }
            
            // 启动或恢复线程
            if (vis_thd_id == 0) {
                // 创建新线程
                if (pthread_create(&vis_thd_id, NULL, encode_thread_mjpeg, mjpeg_encoder) != 0) {
                    printf("创建可见光线程失败\n");
                    VIDEO_SELECT = -1;
                    video_encoder_destroy(mjpeg_encoder);
                    mjpeg_encoder = NULL;
                } else {
                    printf("可见光线程已启动，ID=%lu\n", (unsigned long)vis_thd_id);
                }
            } else {
                // 唤醒可能处于暂停状态的线程
                pthread_mutex_lock(&mjpeg_encoder_exit_mutex);
                pthread_cond_signal(&mjpeg_encoder_exit_cond);
                pthread_mutex_unlock(&mjpeg_encoder_exit_mutex);
            }
            
            VIDEO_SELECT = VIDEO_DEV_VISIBLE;
            pthread_mutex_unlock(&select_video_lock);
            break;
#endif            
        }
       case 0x11: {// 打开可见光 640*480
#if 1
            pthread_mutex_lock(&select_video_lock);         
            thread1_write_data_to_uart = 1;
            
                // 检查线程是否已经在运行
                if (VIDEO_SELECT == VIDEO_DEV_VISIBLE) {
                    // 检查线程是否存在并且未请求退出
                    if (vis_thd_id != 0 && !thread1_should_exit) {
                        thread1_write_data_to_uart = 1;
                        printf("警告：可见光线程已在运行，无需重复启动\n");
                        pthread_mutex_unlock(&select_video_lock);
                        break;
                    }
                    
                    // 线程存在但请求退出，等待其结束
                    if (vis_thd_id != 0) {
                        thread1_should_exit = 1;
                        pthread_mutex_unlock(&select_video_lock);
                        
                        // 等待线程退出
                        signal_thread_to_exit(&vis_thd_id, &thread1_should_exit);
                        
                        pthread_mutex_lock(&select_video_lock);
                    }
                }
                
                // 设置当前视频设备为可见光
                VIDEO_SELECT = VIDEO_DEV_VISIBLE;
                thread1_should_exit = 0; // 重置退出标志
                
                pthread_mutex_unlock(&select_video_lock);
                
                // 全局变量声明（确保mjpeg_encoder为全局变量）
                static VideoEncoderContext *mjpeg_encoder = NULL;
                
                // 若编码器已存在但未运行，重新初始化
                if (mjpeg_encoder != NULL && !mjpeg_encoder->is_running) {
                    printf("##[DEBUG] 编码器已存在但未运行，重新初始化\n");
                    int ret = video_encoder_init(mjpeg_encoder);
                    if (ret != 0) {
                        fprintf(stderr, "编码器重新初始化失败，错误码: %d\n", ret);
                        break;
                    }
                }
                
                // 首次创建编码器
                if (mjpeg_encoder == NULL) {
                    const EncoderParams params = {"/dev/video20", "output_h265.h265", 640, 480, 30, 0, ENCODING_FORMAT_H265, 1};
                    // 创建编码器
                    mjpeg_encoder = video_encoder_create(&params);
                    if (!mjpeg_encoder) {
                        fprintf(stderr, "创建编码器失败\n");
                        VIDEO_SELECT = -1;
                        break;
                    }
                    
                    // 初始化编码器
                    int ret = video_encoder_init(mjpeg_encoder);
                    if (ret != 0) {
                        fprintf(stderr, "编码器初始化失败，错误码: %d\n", ret);
                        video_encoder_destroy(mjpeg_encoder);
                        mjpeg_encoder = NULL;
                        VIDEO_SELECT = -1;
                        break;
                    }
                }
                
                // 创建新的编码线程（仅当线程未启动时）
                if (vis_thd_id == 0 || !mjpeg_encoder->is_running) {
                    if (pthread_create(&vis_thd_id, NULL, encode_thread_mjpeg, mjpeg_encoder) != 0) {
                        printf("创建可见光线程失败\n");
                        VIDEO_SELECT = -1;
                    } else {
                        printf("可见光线程已启动，ID=%lu\n", (unsigned long)vis_thd_id);
                    }
                }
                
                thread1_write_data_to_uart = 1;
                break;
#else
#endif            
        }
        case 0x02: { // 关闭可见光,不需要退出，关闭串口发送流通道就好了，标志位thread1_write_data_to_uart
#if 1
            pthread_mutex_lock(&select_video_lock);
            // 关闭串口写入流通道
            thread1_write_data_to_uart = 0;
            // 重置设备选择
            VIDEO_SELECT = -1;
            
            pthread_mutex_unlock(&select_video_lock);
            printf("可见光线程: 已停止并关闭串口写入流通道\n");
            break;
#else

            pthread_mutex_lock(&select_video_lock);
            
            if (mjpeg_encoder != NULL && mjpeg_encoder->is_running) {
                // 暂停编码但不退出线程
                video_encoder_pause(mjpeg_encoder);
                printf("可见光线程: 已暂停编码\n");
            }
            
            // 不需要退出线程，保留上下文
            // 也不需要销毁编码器，保留资源
            
            VIDEO_SELECT = -1;
            pthread_mutex_unlock(&select_video_lock);
            break;
#endif

        }
        /* 红外模块命令范围 */
        case 0x03: { // 打开红外供电链路
            pthread_mutex_lock(&select_video_lock);
            
            // 检查线程是否已经在运行
            if (VIDEO_SELECT == VIDEO_DEV_IR) {
                // 检查线程是否存在并且未请求退出
                if (icr_thd_id != 0 && thread2_should_exit == 0) {
                    printf("警告：可见光线程已在运行，无需重复启动\n");
                    pthread_mutex_unlock(&select_video_lock);
                    break;
                }
                
                // 线程存在但请求退出，等待其结束
                if (icr_thd_id != 0) {
                    thread2_should_exit = 1;
                    pthread_mutex_unlock(&select_video_lock);
                    
                    // 等待线程退出
                    signal_thread_to_exit(&icr_thd_id, &thread2_should_exit);
                    
                    pthread_mutex_lock(&select_video_lock);
                }
            }
            
            // 设置当前视频设备为可见光
            VIDEO_SELECT = VIDEO_DEV_IR;
            thread2_should_exit = 0; // 重置退出标志
            
            pthread_mutex_unlock(&select_video_lock);
            
            // 创建新的编码线程
            if (pthread_create(&icr_thd_id, NULL, encoder_thd2_icr, NULL) != 0) {
                printf("创建可见光线程失败\n");
                VIDEO_SELECT = -1;
            } else {
                printf("可见光线程已启动，ID=%lu\n", (unsigned long)icr_thd_id);
            }
            thread2_write_data_to_uart = 1;
            break;
        }
        case 0x04: { // 关闭红外供电链路 -- （基本不用，直接关机就行）
            pthread_mutex_lock(&select_video_lock);
            thread2_write_data_to_uart = 0;
            thread2_should_exit  = 1;// 设置退出标志替代直接取消
            pthread_mutex_unlock(&select_video_lock);
            // 等待线程退出（使用新的辅助函数）
            if (icr_thd_id==0)
            {
                break;
            }
            
            signal_thread_to_exit(&icr_thd_id, &thread2_should_exit);
    
            VIDEO_SELECT = -1; //
            printf("可见光线程: 已强制终止并回收资源\n");

            break;
        }

        case 0x53: { // 对焦
#if 1
            if ((buf[8] == 0x01) && (buf[9] == 0x03)) // 可见光持续对焦+
            {
                ret = send_data(g_uart_vis,SLP_VIS_CMD_CONTINUOUS_FOCUS_UP,sizeof(SLP_VIS_CMD_CONTINUOUS_FOCUS_UP));
                log_info(LOG_OK,"##可见光持续对焦+ 发送");
                break;
            }
            if ((buf[8] == 0x01) && (buf[9] == 0x04)) // 可见光持续对焦-
            {
                ret = send_data(g_uart_vis,SLP_VIS_CMD_CONTINUOUS_FOCUS_DOWN,sizeof(SLP_VIS_CMD_CONTINUOUS_FOCUS_DOWN));
                log_info(LOG_OK,"##可见光持续对焦- 发送");
                break;

            }
            if ((buf[8] == 0x02) && (buf[9] == 0x03)) // 红外镜头持续对焦+
            {
            #if 0
                uint8_t SLP_ICR_CMD_CONTINUOUS_FOCUS_UP[7] = {0xFF, 0x01, 0x01, 0x00, 0x00,0x00, 0x02}; //红外持续聚焦变倍+
                ret = send_data(g_uart_lens,SLP_ICR_CMD_CONTINUOUS_FOCUS_UP,sizeof(SLP_ICR_CMD_CONTINUOUS_FOCUS_UP));
                log_info(LOG_OK,"##红外镜头持续对焦+ 发送");
                break;
            #else
                const char* FocusUp = "sudo /home/remote/project/build/test_serial_demo single /dev/ttyS4 9600 8 1 N hex FF 01 01 00 00 00 02";
                printf("执行红外镜头持续对焦+命令: %s\n", FocusUp);
                
                int status = system(FocusUp);
                if (status == -1) {
                    perror("打开红外镜头持续对焦+命令执行失败");
                } else if (WIFEXITED(status)) {
                    printf("打开命令执行完毕，退出状态: %d\n", WEXITSTATUS(status));
                } else if (WIFSIGNALED(status)) {
                    printf("打开命令被信号终止: %d\n", WTERMSIG(status));
                }
                break;
            #endif
            }
            if ((buf[8] == 0x02) && (buf[9] == 0x04)) // 红外镜头持续对焦-
            {

            #if 0
                uint8_t SLP_ICR_CMD_CONTINUOUS_FOCUS_DOWN[7] = {0xFF, 0x01, 0x00, 0x80, 0x00,0x00, 0x81}; //红外持续聚焦变倍-
                ret = send_data(g_uart_lens,SLP_VIS_CMD_CONTINUOUS_FOCUS_DOWN,sizeof(SLP_VIS_CMD_CONTINUOUS_FOCUS_DOWN));
                log_info(LOG_OK,"##红外镜头持续对焦- 发送");
                break;
            #else
                const char* FocusDown = "sudo /home/remote/project/build/test_serial_demo single /dev/ttyS4 9600 8 1 N hex FF 01 00 80 00 00 81";
                printf("执行红外镜头持续对焦-命令: %s\n", FocusDown);
                
                int status = system(FocusDown);
                if (status == -1) {
                    perror("打开红外镜头持续对焦-命令执行失败");
                } else if (WIFEXITED(status)) {
                    printf("打开命令执行完毕，退出状态: %d\n", WEXITSTATUS(status));
                } else if (WIFSIGNALED(status)) {
                    printf("打开命令被信号终止: %d\n", WTERMSIG(status));
                }
                break;
            #endif
            }
#else
            if ((VIDEO_SELECT == VIDEO_DEV_VISIBLE) && (0x01 == params[4])) { // 可见光对焦
                if (0x03 == params[5]) //持续对焦+
                {
                    if( send_data(g_uart_vis,SLP_VIS_CMD_CONTINUOUS_FOCUS_UP,sizeof(SLP_VIS_CMD_CONTINUOUS_FOCUS_UP)) < 0)
                    {
                        printf("send SLP_VIS_CMD_CONTINUOUS_FOCUS_UP filed\n"); 
                    }
                }
                if (0x04 == params[5]) //持续对焦-
                {
                    if( send_data(g_uart_vis,SLP_VIS_CMD_CONTINUOUS_FOCUS_DOWN,sizeof(SLP_VIS_CMD_CONTINUOUS_FOCUS_DOWN)) < 0)
                    {
                        printf("send SLP_VIS_CMD_CONTINUOUS_FOCUS_DOWN filed\n"); 
                    }
                }

            } else if ((VIDEO_SELECT == VIDEO_DEV_IR) && (0x02 == params[4])) { // 红外对焦
                if (0x03 == params[5]) //持续对焦+
                {
                    if( send_data(g_uart_lens,SLP_ICR_CMD_CONTINUOUS_FOCUS_UP,sizeof(SLP_ICR_CMD_CONTINUOUS_FOCUS_UP)) < 0)
                    {
                        printf("send SLP_ICR_CMD_CONTINUOUS_FOCUS_UP filed\n"); 
                    }
                }
                if (0x04 == params[5]) //持续对焦-
                {
                    if( send_data(g_uart_lens,SLP_ICR_CMD_CONTINUOUS_FOCUS_DOWN,sizeof(SLP_ICR_CMD_CONTINUOUS_FOCUS_DOWN)) < 0)
                    {
                        printf("send SLP_ICR_CMD_CONTINUOUS_FOCUS_DOWN filed\n"); 
                    }
                }
                if (0x07 == params[5]) //单步对焦+
                {
                    if( send_data(g_uart_lens,SLP_ICR_CMD_SINGLESTEP_FOCUS_UP,sizeof(SLP_ICR_CMD_SINGLESTEP_FOCUS_UP)) < 0)
                    {
                        printf("send SLP_ICR_CMD_SINGLESTEP_FOCUS_UP filed\n"); 
                    }
                }
                if (0x08 == params[5]) //单步对焦-
                {
                    if( send_data(g_uart_lens,SLP_ICR_CMD_SINGLESTEP_FOCUS_DOWN,sizeof(SLP_ICR_CMD_SINGLESTEP_FOCUS_DOWN)) < 0)
                    {
                        printf("send SLP_ICR_CMD_SINGLESTEP_FOCUS_DOWN filed\n"); 
                    }
                }
                
            } else {
                perror("Error: No active video device to set zoom\n");
            }

 
#endif
            break;
        }

        case 0x54: { // 变倍
#if 1
            if ((buf[8] == 0x01) && (buf[9] == 0x01)) // 可见光持续变倍+
            {
                ret = send_data(g_uart_vis,SLP_VIS_CMD_CONTINUOUS_ZOOM_UP,sizeof(SLP_VIS_CMD_CONTINUOUS_ZOOM_UP));
                log_info(LOG_OK,"##可见光持续变倍+ 发送");
                break;
            }
            if ((buf[8] == 0x01) && (buf[9]  == 0x02))// 可见光持续变倍-
            {
                ret = send_data(g_uart_vis,SLP_VIS_CMD_CONTINUOUS_ZOOM_DOWN,sizeof(SLP_VIS_CMD_CONTINUOUS_ZOOM_DOWN));
                break;
            }
            if ((buf[8] == 0x02) && (buf[9] == 0x01))// 红外镜头持续变倍+
            {
            #if 0
                uint8_t SLP_ICR_CMD_CONTINUOUS_ZOOM_UP[7] = {0xFF, 0x01, 0x00, 0x20, 0x00,0x00, 0x21}; //红外持续变倍+
                ret = send_data(g_uart_lens,SLP_ICR_CMD_CONTINUOUS_ZOOM_UP,sizeof(SLP_ICR_CMD_CONTINUOUS_ZOOM_UP));
                log_info(LOG_OK,"##红外镜头持续变倍+ 发送 %d",ret);
                break;
            #else
                const char* ZoomUp = "sudo /home/remote/project/build/test_serial_demo single /dev/ttyS4 9600 8 1 N hex FF 01 00 20 00 00 21";
                printf("执行红外镜头持续变倍+命令: %s\n", ZoomUp);
                
                int status = system(ZoomUp);
                if (status == -1) {
                    perror("打开红外镜头持续变倍+命令执行失败");
                } else if (WIFEXITED(status)) {
                    printf("打开命令执行完毕，退出状态: %d\n", WEXITSTATUS(status));
                } else if (WIFSIGNALED(status)) {
                    printf("打开命令被信号终止: %d\n", WTERMSIG(status));
                }
                break;
            #endif
            }
            if ((buf[8] == 0x02) && (buf[9] == 0x02))// 红外镜头持续变倍-
            {
            #if 0
                uint8_t SLP_ICR_CMD_CONTINUOUS_ZOOM_DOWN[7] = {0xFF, 0x01, 0x00, 0x40, 0x00,0x00, 0x41}; //红外持续变倍-
                ret = send_data(g_uart_lens,SLP_ICR_CMD_CONTINUOUS_ZOOM_DOWN,sizeof(SLP_ICR_CMD_CONTINUOUS_ZOOM_DOWN));
                log_info(LOG_OK,"##红外镜头持续变倍- 发送,%d",ret);
                break;
            #else
                const char* ZoomDown = "sudo /home/remote/project/build/test_serial_demo single /dev/ttyS4 9600 8 1 N hex FF 01 00 40 00 00 41";
                printf("执行红外镜头持续变倍-命令: %s\n", ZoomDown);
                
                int status = system(ZoomDown);
                if (status == -1) {
                    perror("打开红外镜头持续变倍-命令执行失败");
                } else if (WIFEXITED(status)) {
                    printf("打开命令执行完毕，退出状态: %d\n", WEXITSTATUS(status));
                } else if (WIFSIGNALED(status)) {
                    printf("打开命令被信号终止: %d\n", WTERMSIG(status));
                }
                break;
            #endif
            }      

#else
            if ((VIDEO_SELECT == VIDEO_DEV_VISIBLE) && (0x01 == params[4])) { // 可见光变倍
                if (0x01 == params[5]) //持续变倍+
                {
                    if( send_data(g_uart_vis,SLP_VIS_CMD_CONTINUOUS_ZOOM_UP,sizeof(SLP_VIS_CMD_CONTINUOUS_ZOOM_UP)) < 0)
                    {
                        printf("send SLP_VIS_CMD_CONTINUOUS_ZOOM_UP filed\n"); 
                    }
                }
                if (0x02 == params[5]) //持续变倍-
                {
                    if( send_data(g_uart_vis,SLP_VIS_CMD_CONTINUOUS_ZOOM_DOWN,sizeof(SLP_VIS_CMD_CONTINUOUS_ZOOM_DOWN)) < 0)
                    {
                        printf("send SLP_VIS_CMD_CONTINUOUS_ZOOM_DOWN filed\n"); 
                    }
                }

            } else if ((VIDEO_SELECT == VIDEO_DEV_IR) && (0x02 == params[4])) { // 红外变倍
                if (0x01 == params[5]) //持续变倍+
                {
                    if( send_data(g_uart_lens,SLP_ICR_CMD_CONTINUOUS_ZOOM_UP,sizeof(SLP_ICR_CMD_CONTINUOUS_ZOOM_UP)) < 0)
                    {
                        printf("send SLP_ICR_CMD_CONTINUOUS_ZOOM_UP filed\n"); 
                    }
                }
                if (0x02 == params[5]) //持续变倍-
                {
                    if( send_data(g_uart_lens,SLP_ICR_CMD_CONTINUOUS_ZOOM_DOWN,sizeof(SLP_ICR_CMD_CONTINUOUS_ZOOM_DOWN)) < 0)
                    {
                        printf("send SLP_ICR_CMD_CONTINUOUS_ZOOM_DOWN filed\n"); 
                    }
                }
                if (0x05 == params[5]) //单步变倍+
                {
                    if( send_data(g_uart_lens,SLP_ICR_CMD_SINGLESTEP_ZOOM_UP,sizeof(SLP_ICR_CMD_SINGLESTEP_ZOOM_UP)) < 0)
                    {
                        printf("send SLP_ICR_CMD_SINGLESTEP_ZOOM_UP filed\n"); 
                    }
                }
                if (0x06 == params[5]) //单步变倍-
                {
                    if( send_data(g_uart_lens,SLP_ICR_CMD_SINGLESTEP_ZOOM_DOWN,sizeof(SLP_ICR_CMD_SINGLESTEP_ZOOM_DOWN)) < 0)
                    {
                        printf("send SLP_ICR_CMD_SINGLESTEP_ZOOM_DOWN filed\n"); 
                    }
                }
                
            }  
            else {
                perror("Error: No active video device to set autofocus\n");
            }
#endif
            break;
        }

        case 0x58: { // 数字变倍 开
#if 1
            if (buf[9] == 0x00)
            {
                ret = send_data(g_uart_vis,SLP_VIS_CMD_DIGITALZOOM_ON,sizeof(SLP_VIS_CMD_DIGITALZOOM_ON));
                log_info(LOG_OK,"##数字变倍 开 -> 可见光 发送");
                break;
            }
            if (buf[9] == 0x01)
            {
                ret = send_data(g_uart_vis,SLP_VIS_CMD_DIGITAL_ZOOM_SEPARATE,sizeof(SLP_VIS_CMD_DIGITAL_ZOOM_SEPARATE));
                log_info(LOG_OK,"##数字变倍 分离模式 开 -> 可见光 发送");
                break;
            }
            if (buf[9] == 0x02)
            {
                ret =  send_data(g_uart_vis,SLP_VIS_CMD_DIGITAL_ZOOM_COMBINED,sizeof(SLP_VIS_CMD_DIGITAL_ZOOM_COMBINED));
                log_info(LOG_OK,"##数字变倍 结合模式 开 -> 可见光 发送");
                break;
            }
            
#else
            if ((VIDEO_SELECT == VIDEO_DEV_VISIBLE) && (0x01 == params[4])) {
                // 发送可见光数字变倍命令
                    if( send_data(g_uart_vis,SLP_VIS_CMD_DIGITAL_ZOOM_COMBINED,sizeof(SLP_VIS_CMD_DIGITAL_ZOOM_COMBINED)) < 0)
                    {
                        printf("send SLP_ICR_CMD_SINGLESTEP_FOCUS_DOWN filed\n"); 
                    }
            } else {
                perror("Error: No active video device to enable digital zoom\n");
            }
#endif     
            break;
        }

        case 0x59: { // 数字变倍 关
#if 1
            ret = send_data(g_uart_vis,SLP_VIS_CMD_DIGITALZOOM_OFF,sizeof(SLP_VIS_CMD_DIGITALZOOM_OFF));
            log_info(LOG_OK,"##数字变倍 关 -> 可见光 发送");
    
#else
            if ((VIDEO_SELECT == VIDEO_DEV_VISIBLE) && (0x01 == params[4])) {
                // 发送可见光数字变倍关闭命令
                unsigned char VIS_CMD_DIGITAL_ZOOM_OFF[6] = {0x55, 0xAA, 0x0B, params[0], 0x00, 0xAA};
                    if( send_data(g_uart_vis,VIS_CMD_DIGITAL_ZOOM_OFF,sizeof(VIS_CMD_DIGITAL_ZOOM_OFF)) < 0)
                    {
                        printf("send VIS_CMD_DIGITAL_ZOOM_OFF filed\n"); 
                    }
            } else {
                perror("Error: No active video device to disable digital zoom\n");
            }
#endif
            break;
        }

        case 0x60: { // 停止相关
#if 1
            if ((buf[8] == 0x01) && (buf[9] == 0x01)) // 关闭可见光变倍操作
            {
                ret = send_data(g_uart_vis,SLP_VIS_CMD_CONTINUOUS_ZOOM_STOP,sizeof(SLP_VIS_CMD_CONTINUOUS_ZOOM_STOP));
                log_info(LOG_OK,"##关闭可见光变倍操作 发送");
                break;
            } 
            if ((buf[8] == 0x01) && (buf[9] == 0x02)) //关闭可见光变焦操作
            {
                ret = send_data(g_uart_vis,SLP_VIS_CMD_CONTINUOUS_FOCUS_STOP,sizeof(SLP_VIS_CMD_CONTINUOUS_FOCUS_STOP));
                log_info(LOG_OK,"##关闭可见光变焦操作 发送"); 
                break;
            } 
            if ((buf[8] == 0x02) && (buf[9] == 0x01)) //关闭红外变倍操作&变焦操作
            {
            #if 0
                uint8_t SLP_ICR_CMD_STOP_ZF[7] = {0xFF, 0x01, 0x00, 0x00, 0x00,0x00, 0x01}; //变倍和聚焦停止
                ret = send_data(g_uart_lens,SLP_ICR_CMD_STOP_ZF,sizeof(SLP_ICR_CMD_STOP_ZF));
                log_info(LOG_OK,"##关闭红外变倍操作&变焦操作 发送"); 
                break;
            #else
                const char* Stop = "sudo /home/remote/project/build/test_serial_demo single /dev/ttyS4 9600 8 1 N hex FF 01 00 00 00 00 01";
                printf("执行关闭红外变倍操作变焦操作命令: %s\n", Stop);
                
                int status = system(Stop);
                if (status == -1) {
                    perror("打开关闭红外变倍操作变焦操作命令执行失败");
                } else if (WIFEXITED(status)) {
                    printf("打开命令执行完毕，退出状态: %d\n", WEXITSTATUS(status));
                } else if (WIFSIGNALED(status)) {
                    printf("打开命令被信号终止: %d\n", WTERMSIG(status));
                }
                break;
            #endif
            }
#else
            if ((VIDEO_SELECT == VIDEO_DEV_VISIBLE) && (0x01 == params[4])) { // 可见光
                if (0xF1 == params[5]) //停止可见变倍
                {
                    if( send_data(g_uart_vis,SLP_VIS_CMD_CONTINUOUS_ZOOM_STOP,sizeof(SLP_VIS_CMD_CONTINUOUS_ZOOM_STOP)) < 0)
                    {
                        printf("send SLP_VIS_CMD_CONTINUOUS_ZOOM_STOP filed\n"); 
                    }
                }
                if (0xF2 == params[5]) //停止可见聚焦
                {
                    if( send_data(g_uart_vis,SLP_VIS_CMD_CONTINUOUS_FOCUS_STOP,sizeof(SLP_VIS_CMD_CONTINUOUS_FOCUS_STOP)) < 0)
                    {
                        printf("send SLP_VIS_CMD_CONTINUOUS_FOCUS_STOP filed\n"); 
                    }
                }

            } else if ((VIDEO_SELECT == VIDEO_DEV_IR) && (0x02 == params[4])) { // 红外
                if (0xF0 == params[5]) //停止红外
                {
                    if( send_data(g_uart_lens,SLP_ICR_CMD_STOP_ZF,sizeof(SLP_ICR_CMD_STOP_ZF)) < 0)
                    {
                        printf("send SLP_ICR_CMD_STOP_ZF filed\n"); 
                    }
                }
                
            } else {
                perror("Error: No active video device to set autofocus\n");
            }
#endif
            break;
        }

        case 0x61: { // 模式相关
            if ((buf[8] == 0x01) && (buf[9] == 0x02)) // 手动模式
            {
                ret = send_data(g_uart_vis,SLP_VIS_CMD_MANNUAL_MODE,sizeof(SLP_VIS_CMD_MANNUAL_MODE));
                log_info(LOG_OK,"##手动模式 发送");
                break;
            } 
            if ((buf[8] == 0x01) && (buf[9] == 0x01)) // 自动模式
            {
                ret = send_data(g_uart_vis,SLP_VIS_CMD_AUTO_MODE,sizeof(SLP_VIS_CMD_AUTO_MODE));
                log_info(LOG_OK,"##自动模式 发送");
                break;
            } 
            if ((buf[8] == 0x01) && (buf[9] == 0x11)) // 垂直翻转开
            {
                uint8_t Flip_Hori_Open[6] = {0x81,0x01,0x04,0x66,0x02,0xFF};
                ret = send_data(g_uart_vis,Flip_Hori_Open,sizeof(Flip_Hori_Open));
                log_info(LOG_OK,"##垂直翻转开 发送");
                break;
            } 
            if ((buf[8] == 0x01) && (buf[9] == 0x10)) // 垂直翻转关
            {
                uint8_t Flip_Hori_Close[6] = {0x81,0x01,0x04,0x66,0x03,0xFF};
                ret = send_data(g_uart_vis,Flip_Hori_Close,sizeof(Flip_Hori_Close));
                log_info(LOG_OK,"##垂直翻转关 发送");
                break;
            } 
            if ((buf[8] == 0x01) && (buf[9] == 0x21)) // 水平翻转开
            {
                uint8_t Ver_Hori_Open[6] = {0x81,0x01,0x04,0x61,0x02,0xFF};
                ret =  send_data(g_uart_vis,Ver_Hori_Open,sizeof(Ver_Hori_Open));
                log_info(LOG_OK,"##水平翻转开 发送");
                break;
            } 
            if ((buf[8] == 0x01) && (buf[9] == 0x20)) // 水平翻转关
            {
                uint8_t Ver_Hori_Close[6] = {0x81,0x01,0x04,0x61,0x03,0xFF};
                ret =  send_data(g_uart_vis,Ver_Hori_Close,sizeof(Ver_Hori_Close));
                log_info(LOG_OK,"##水平翻转关 发送");
                break;
            }
            break;
        }

        case 0x0D: { // 指点跟踪
            break;
        }
        case 0x0E: { // 停止跟踪
            break;
        }
        case 0x0B: { // 红外图像校正
            break;
        }
        case 0x0C: { // 红外gamma调节
            break;
        }
        // case 0x11: { // 红外白热
        //     break;
        // }
        case 0x12: { // 红外黑热
            break;
        }
        case 0x13: { // 打开制冷机
            const char* openCmd = "sudo /home/remote/project/build/test_OpenRefriger_demo";
            printf("执行打开制冷机命令: %s\n", openCmd);
            
            int status = system(openCmd);
            if (status == -1) {
                perror("打开制冷机命令执行失败");
            } else if (WIFEXITED(status)) {
                printf("打开命令执行完毕，退出状态: %d\n", WEXITSTATUS(status));
            } else if (WIFSIGNALED(status)) {
                printf("打开命令被信号终止: %d\n", WTERMSIG(status));
            }
            break;
        }
        case 0x14: { // 关闭制冷机
            const char* closeCmd = "sudo /home/remote/project/build/test_CloseRefriger_demo";
            printf("执行关闭命令: %s\n", closeCmd);
            
            int status = system(closeCmd);
            if (status == -1) {
                perror("关闭制冷机命令执行失败");
            } else if (WIFEXITED(status)) {
                printf("关闭命令执行完毕，退出状态: %d\n", WEXITSTATUS(status));
            } else if (WIFSIGNALED(status)) {
                printf("关闭命令被信号终止: %d\n", WTERMSIG(status));
            }
            break;
        }
#if 1
        case 0x15: { // 红外参数初始化
            ret = send_data(g_uart_icr,SLP_ICR_CMD_SET_OPTION,sizeof(SLP_ICR_CMD_SET_OPTION));
            printf("红外参数初始化发送成功！\n");
            break;
        }
        case 0x16: { // 红外探测器上电
             ret = send_data(g_uart_icr,SLP_ICR_CMD_DETECTOR_POWERON,sizeof(SLP_ICR_CMD_DETECTOR_POWERON));
            printf("红外参数初始化发送成功！\n");
            break;
        }
        case 0x17: { // 红外视频处理电路上电
            ret = send_data(g_uart_icr,SLP_ICR_CMD_VPROCRCUT_POWERON,sizeof(SLP_ICR_CMD_VPROCRCUT_POWERON));
            printf("红外探测器上电 发送成功！\n");
            break;
        }
        case 0x18: { // 红外 开始摄像
            ret = send_data(g_uart_icr,SLP_ICR_CMD_VIDEO_START,sizeof(SLP_ICR_CMD_VIDEO_START));
            printf("红外开始摄像 发送成功！\n");
            break;
        }
        case 0x19: { // 红外 停止摄像
            ret = send_data(g_uart_icr,SLP_ICR_CMD_VIDEO_STOP,sizeof(SLP_ICR_CMD_VIDEO_STOP));
            printf("红外停止摄像 发送成功！\n");
            break;
        }
        /************* */
        case 0x20: { // 红外视频处理电路下电
            ret = send_data(g_uart_icr,SLP_ICR_CMD_VPROCRCUT_POWEROFF,sizeof(SLP_ICR_CMD_VPROCRCUT_POWEROFF));
            printf("红外视频处理电路下电 发送成功！\n");
            break;
        }
        case 0x21: { // 红外探测器下电
            ret = send_data(g_uart_icr,SLP_ICR_CMD_SET_OPTION,sizeof(SLP_ICR_CMD_SET_OPTION));
            log_info(1,"红外参数初始化发送成功！\n");
            break;
        }
        /************* */
        case 0x22: { // 红外探测器链路参数初始化
            //1 红外参数初始化
            ret = send_data(g_uart_icr,SLP_ICR_CMD_SET_OPTION,sizeof(SLP_ICR_CMD_SET_OPTION));
            usleep(50000);
            //2  红外探测器上电
            ret = send_data(g_uart_icr,SLP_ICR_CMD_DETECTOR_POWERON,sizeof(SLP_ICR_CMD_DETECTOR_POWERON));
            usleep(50000);
            //3  红外视频链路上电
            ret = send_data(g_uart_icr,SLP_ICR_CMD_VPROCRCUT_POWERON,sizeof(SLP_ICR_CMD_VPROCRCUT_POWERON));
            usleep(50000);
            //4 红外摄像开
            ret =  send_data(g_uart_icr,SLP_ICR_CMD_VIDEO_START,sizeof(SLP_ICR_CMD_VIDEO_START));
            break;
        }
#else
        case 0xA1: { // 红外链路初始化：红外参数初始化-> 红外探测器上电 -> 红外视频处理电路上电
            if( send_data(g_uart_icr,SLP_ICR_CMD_DETECTOR_POWEROFF,sizeof(SLP_ICR_CMD_DETECTOR_POWEROFF)) < 0)
            {
                printf("send SLP_ICR_CMD_DETECTOR_POWEROFF filed\n"); 
            }
            printf("红外探测器下电 发送成功！\n");
            break;
        }
        case 0xA2: { // 开始摄像

            if( send_data(g_uart_icr,SLP_ICR_CMD_DETECTOR_POWEROFF,sizeof(SLP_ICR_CMD_DETECTOR_POWEROFF)) < 0)
            {
                printf("send SLP_ICR_CMD_DETECTOR_POWEROFF filed\n"); 
            }
            printf("红外探测器下电 发送成功！\n");
            break;
        }
        case 0xA2: { // 关闭摄像

            if( send_data(g_uart_icr,SLP_ICR_CMD_DETECTOR_POWEROFF,sizeof(SLP_ICR_CMD_DETECTOR_POWEROFF)) < 0)
            {
                printf("send SLP_ICR_CMD_DETECTOR_POWEROFF filed\n"); 
            }
            printf("红外探测器下电 发送成功！\n");
            break;
        }


#endif
        default:
        {
            printf("Warning: Unknown control code 0x%02X\n", buf[2]);
            printf("=== UNHANDLED DATA DETAIL ===\n");
            
            // 顶部边框
            printf("╔");
            for (int i = 0; i < 49; i++) printf("═");
            printf("╗\n");
            
            // 数据内容
            for (int i = 0; i < len; i++) {
                if (i % 16 == 0) printf("║ ");  // 行首边框
                printf("%02X ", buf[i]);
                if ((i + 1) % 16 == 0 || i == len - 1) {
                    // 填充空格使每行宽度一致
                    for (int j = 0; j < (16 - (i % 16) - 1) * 3; j++) printf(" ");
                    printf(" ║\n");  // 行尾边框
                }
            }
            
            // 底部边框
            printf("╚");
            for (int i = 0; i < 49; i++) printf("═");
            printf("╝\n");
            
            printf("================================\n");
            break;
        }
    }
}

//可见光默认上电初始化：

void uart_vis_init(void)
{
    int ret = -1;
    //参数初始化
    /*1. 相机通信模式*/
    uint8_t CAM_MODE_COMM[9] = {0x81, 0x0A, 0x02, 0x00, 0x00, 0x00,0x00, 0x00, 0xFF};
    /*2. 全自动模式：聚焦等*/
    uint8_t AUTO_MODE[6] = {0x81, 0x01, 0x04, 0x39, 0x00, 0xFF};
    uint8_t FOUC_MODE[6] = {0x81, 0x01, 0x04, 0x38, 0x02, 0xFF};

    ret = send_data(g_uart_vis,CAM_MODE_COMM,sizeof(CAM_MODE_COMM));
    ret = send_data(g_uart_vis,AUTO_MODE,sizeof(AUTO_MODE));
    ret = send_data(g_uart_vis,FOUC_MODE,sizeof(FOUC_MODE));
    log_info(1,"uart_vis_init ok");
}